home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / lisp / eulisp / you-075a.lha / you-075a / listops.c < prev    next >
C/C++ Source or Header  |  1992-06-18  |  8KB  |  364 lines

  1. /* ******************************************************************** */
  2. /* listops.c         Copyright (C) Codemist and University of Bath 1989 */
  3. /*                                                                      */
  4. /* further list operations                                        */
  5. /* ******************************************************************** */
  6.  
  7. /*
  8.  * $Id: listops.c,v 1.6 1992/03/15 19:47:42 pab Exp $
  9.  *
  10.  * $Log: listops.c,v $
  11.  * Revision 1.6  1992/03/15  19:47:42  pab
  12.  * last_pair fix
  13.  *
  14.  * Revision 1.5  1992/01/07  22:15:36  pab
  15.  * ncc compatable, plus backtrace
  16.  *
  17.  * Revision 1.4  1991/12/22  15:14:15  pab
  18.  * Xmas revision
  19.  *
  20.  * Revision 1.3  1991/09/22  19:14:35  pab
  21.  * Fixed obvious bugs
  22.  *
  23.  * Revision 1.2  1991/09/11  12:07:20  pab
  24.  * 11/9/91 First Alpha release of modified system
  25.  *
  26.  * Revision 1.1  1991/08/12  16:49:43  pab
  27.  * Initial revision
  28.  *
  29.  * Revision 1.4  1991/02/13  18:22:07  kjp
  30.  * Pass.
  31.  *
  32.  */
  33.  
  34. /*
  35.  * Change Log:
  36.  *   Version 1, March 1990 (Compiler rationalisation)
  37.  */
  38.  
  39. #include "defs.h"
  40. #include "structs.h"
  41. #include "funcalls.h"
  42.  
  43. #include "error.h"
  44. #include "global.h"
  45. #include "modboot.h"
  46. #include "symboot.h"
  47. #include "calls.h"
  48. #include "modules.h"
  49. #include "ngenerics.h"
  50.  
  51. LispObject flat_list_copy(LispObject *);
  52.  
  53. EUFUN_1( Fn_null, form)
  54. {
  55.   return (form==nil?lisptrue:nil);
  56. }
  57. EUFUN_CLOSE
  58.  
  59.                 /* Destructive append */
  60. EUFUN_2( Fn_nconc,  form1, form2)
  61. {
  62.   LispObject p = form1;
  63.   if (!is_cons(form1)) return(form2);
  64.   while (CDR(p)!=nil) p = CDR(p);
  65.   CDR(p) = form2;
  66.   return form1;
  67. }
  68. EUFUN_CLOSE
  69.  
  70. EUFUN_2( Fn_append,  l1, l2)
  71. {
  72.   LispObject endptr,walker,val;
  73.  
  74.   if (!is_cons(l1)) return(l2);
  75.  
  76.   /* reasonable append */
  77.   
  78.   val = EUCALL_2(Fn_cons,CAR(l1),nil);
  79.   STACK_TMP(val);
  80.   endptr = val;
  81.   walker = CDR(ARG_0(stackbase)/*l1*/);
  82.   while (is_cons(walker))
  83.     {
  84.       LispObject xx;
  85.       STACK_TMP(endptr);
  86.       STACK_TMP(CDR(walker));
  87.       xx = EUCALL_2(Fn_cons, CAR(walker), nil);
  88.       UNSTACK_TMP(walker);
  89.       UNSTACK_TMP(endptr);
  90.       CDR(endptr)=xx;
  91.       endptr=CDR(endptr);
  92.     }
  93.   CDR(endptr) = ARG_1(stackbase)/*l2*/;
  94.   UNSTACK_TMP(val);
  95.   return(val);
  96. }
  97. EUFUN_CLOSE
  98.  
  99.                 /* Simple predicate for NULL */
  100. EUFUN_1( Fn_lastpair, form)
  101. {
  102.   while (!is_cons(form))
  103.     form = CallError(stacktop,"Not a list in last-pair",form,CONTINUABLE);
  104.   while (is_cons(form) && CDR(form)!=nil)
  105.     form = CDR(form);
  106.   return form;
  107. }
  108. EUFUN_CLOSE
  109.  
  110. EUFUN_1( Fn_nreverse, form)
  111. {
  112.   LispObject x=nil;
  113.   while (form!=nil) {
  114.     LispObject y = CDR(form);
  115.     CDR(form) = x;
  116.     x = form;
  117.     form = y;
  118.   }
  119.   return x;
  120. }
  121. EUFUN_CLOSE
  122.  
  123. EUFUN_3( Fn_assoc, obj, list, fn)
  124. {
  125.   while (list!=nil) {
  126.     LispObject xx;
  127.     EUCALLSET_3(xx,apply2,ARG_2(stackbase),ARG_0(stackbase),CAR(CAR(list)));
  128.     if (xx != nil)  {
  129.       list=ARG_1(stackbase);
  130.       return CAR(list);
  131.     }
  132.     list = ARG_1(stackbase);
  133.     list = CDR(list);
  134.     ARG_1(stackbase) = list;
  135.   }
  136.   return nil;
  137. }
  138. EUFUN_CLOSE
  139.  
  140. EUFUN_3( Fn_member, obj, list, fn)
  141. {
  142.   while (list!=nil) {
  143.     if (EUCALL_3(apply2,ARG_2(stackbase),ARG_0(stackbase),CAR(list)) != nil) {
  144.       return ARG_1(stackbase);
  145.     }
  146.     list = ARG_1(stackbase);
  147.     list = CDR(list);
  148.     ARG_1(stackbase) = list;
  149.   }
  150.   return nil;
  151. }
  152. EUFUN_CLOSE
  153.  
  154. EUFUN_2( Fn_memq,  obj, list)
  155. {
  156.   if (!is_cons(list) && list != nil)
  157.     CallError(stacktop,"memq: non-lists passed",list,NONCONTINUABLE);
  158.  
  159.   while (is_cons(list)) {
  160.     if (obj == CAR(list))
  161.       return(lisptrue);
  162.     else
  163.       list = CDR(list);
  164.   }
  165.   
  166.   return(nil);
  167. }
  168. EUFUN_CLOSE
  169.  
  170. /* ******************************************************************** */
  171. /*                            Lisp Mappers                              */
  172. /* ******************************************************************** */
  173.  
  174. static LispObject mapcar_apply_args(LispObject *stackbase, LispObject set)
  175. {
  176.   LispObject walker,res,ptr;
  177.   LispObject *stacktop=stackbase+1;
  178.  
  179.   ARG_0(stackbase)=nil;
  180.   res = nil; ptr = nil;
  181.  
  182.   walker = set;
  183.   while (is_cons(walker)) 
  184.     {
  185.       if (!is_cons(CAR(walker))) 
  186.     return(nil);
  187.  
  188.       STACK_TMP(CDR(walker));
  189.       if (ptr == nil)
  190.     {
  191.       EUCALLSET_2(res, Fn_cons,CAR(CAR(walker)),nil);
  192.       ARG_0(stackbase)=res;
  193.       ptr = res;
  194.     }
  195.       else
  196.     {
  197.       LispObject xx;
  198.       STACK_TMP(ptr);
  199.       EUCALLSET_2(xx, Fn_cons, CAR(CAR(walker)),nil);
  200.       UNSTACK_TMP(ptr);
  201.       CDR(ptr) = xx;
  202.       ptr = CDR(ptr);
  203.     }
  204.       UNSTACK_TMP(walker);
  205.     }
  206.   res=ARG_0(stackbase);
  207.   return(res);
  208. }
  209.  
  210. static LispObject mapcar_advance_lists(LispObject set)
  211.   LispObject walker = set;
  212.  
  213.   while (is_cons(walker)) {
  214.     CAR(walker) = CDR(CAR(walker));
  215.     walker = CDR(walker);
  216.   }
  217.   
  218.   return(set);
  219. }
  220.  
  221. EUFUN_3( Fn_mapcar, fn, l1, lists)
  222. {
  223.   LispObject flat_list_copy(LispObject *);
  224.   
  225.   if (!is_cons(l1) && l1 != nil)
  226.     CallError(stacktop,"mapcar: not a list",l1,NONCONTINUABLE);
  227.  
  228.   ARG_3(stackbase)=nil;
  229.   stacktop++;
  230.  
  231.   {
  232.     LispObject set,args;
  233.     LispObject res,ptr,val;
  234.     
  235.     /* More general... */
  236.  
  237.     EUCALLSET_1(set, flat_list_copy, lists);
  238.     EUCALLSET_2(set, Fn_cons,ARG_1(stackbase),set);
  239.  
  240.     res = nil; ptr = nil;
  241.       
  242.     while (TRUE) 
  243.       {
  244.  
  245.     /* Construct args to apply... */
  246.       
  247.     STACK_TMP(set);    
  248.     STACK_TMP(ptr);
  249.     if ((args = mapcar_apply_args(stacktop,set)) == nil) 
  250.       {    
  251.         res=ARG_3(stackbase);
  252.         return(res);
  253.       }
  254.     UNSTACK_TMP(ptr);
  255.     STACK_TMP(ptr);
  256.     EUCALLSET_2(val,module_mv_apply_1,ARG_0(stackbase),args);
  257.     UNSTACK_TMP(ptr);
  258.       
  259.     if (ptr == nil)
  260.       {
  261.         EUCALLSET_2(res, Fn_cons,val,nil);
  262.         ARG_3(stackbase)=res;
  263.         ptr = res;
  264.       }
  265.     else 
  266.       {
  267.         LispObject xx;
  268.         STACK_TMP(ptr);
  269.         EUCALLSET_2(xx, Fn_cons, val,nil);
  270.         UNSTACK_TMP(ptr);
  271.         CDR(ptr) = xx;
  272.         ptr = CDR(ptr);
  273.       }
  274.     UNSTACK_TMP(set);
  275.     mapcar_advance_lists(set);
  276.       }
  277.   }
  278.  
  279.   return(nil);
  280. }
  281. EUFUN_CLOSE
  282.  
  283. EUFUN_3( Fn_mapc, fn, l1, lists)
  284. {
  285.  
  286.   if (!is_cons(l1) && l1 != nil)
  287.     CallError(stacktop,"mapc: not a list",l1,NONCONTINUABLE);
  288.  
  289.   if (FALSE) {
  290.     ;
  291.   }
  292.   else {
  293.     LispObject set,args;
  294.     
  295.     /* More general... */
  296.  
  297.     EUCALLSET_1(set,flat_list_copy,lists);
  298.     EUCALLSET_2(set, Fn_cons,ARG_1(stackbase),set);
  299.  
  300.     while (TRUE) {
  301.       LispObject dummy;
  302.  
  303.       /* Construct args to apply... */
  304.  
  305.       STACK_TMP(set);
  306.       if ((args = mapcar_apply_args(stacktop,set)) == nil) {
  307.     return(nil);
  308.       }
  309.       UNSTACK_TMP(set);
  310.  
  311.       STACK_TMP(set);
  312.       EUCALL_2(module_mv_apply_1,ARG_0(stackbase),args);
  313.       UNSTACK_TMP(set);
  314.       mapcar_advance_lists(set);
  315.     }
  316.   }
  317.  
  318.   return(nil);
  319. }
  320. EUFUN_CLOSE
  321.  
  322. EUFUN_1( flat_list_copy, list)
  323. {
  324.   LispObject xx;
  325.   if (!is_cons(list)) return(nil);
  326.   EUCALLSET_1(xx, flat_list_copy, CDR(list));
  327.   return(EUCALL_2(Fn_cons, CAR(ARG_0(stackbase)),xx));
  328. }
  329. EUFUN_CLOSE
  330.   
  331. /*
  332.  
  333.  * Initialise the module...
  334.  
  335.  */
  336.  
  337. #define LISTOPS_ENTRIES 11
  338. MODULE Module_listops;
  339. LispObject Module_listops_values[LISTOPS_ENTRIES];
  340.  
  341. void initialise_listops(LispObject *stacktop)
  342. {
  343.   open_module(stacktop,
  344.           &Module_listops,
  345.           Module_listops_values,
  346.           "list-operators",
  347.           LISTOPS_ENTRIES);
  348.  
  349.   (void) make_module_function(stacktop,"memq",Fn_memq,2);
  350.   (void) make_module_function(stacktop,"append",Fn_append,2);
  351.   (void) make_module_function(stacktop,"copy-list",flat_list_copy,1);
  352.   (void) make_module_function(stacktop,"null",Fn_null,1);
  353.   (void) make_module_function(stacktop,"nconc",Fn_nconc,2);
  354.   (void) make_module_function(stacktop,"last-pair",Fn_lastpair,1);
  355.   (void) make_module_function(stacktop,"nreverse",Fn_nreverse,1);
  356.   (void) make_module_function(stacktop,"assoc",Fn_assoc,3);
  357.   (void) make_module_function(stacktop,"member",Fn_member,3);
  358.   (void) make_module_function(stacktop,"mapcar",Fn_mapcar,-3);
  359.   (void) make_module_function(stacktop,"mapc",Fn_mapc,-3);
  360.  
  361.   close_module();
  362. }
  363.